package com.gitee.wsl.mathematics.vector.vec4

import com.gitee.wsl.ext.array.DoubleArray
import com.gitee.wsl.io.dataproxy.DataProxy
import com.gitee.wsl.io.dataproxy.asProxy
import com.gitee.wsl.mathematics.vector.vec2.MutableVec2
import com.gitee.wsl.mathematics.vector.vec3.MutableVec3

/**
 * A class representing a four-dimensional vector.
 */
class MutableVec4(override val proxy: DataProxy<Double>):Vec4(proxy=proxy), MutableVector4D<Vec4> {
    constructor(x: Double=0.0,
                y: Double=0.0,
                z: Double=0.0,
                w: Double=0.0):this( DoubleArray(x,y,z,w).asProxy())
    constructor(a: Number) : this(a.toDouble(), a.toDouble(), a.toDouble(), a.toDouble())
    constructor(x: Number, y: Number, z: Number, w: Number) : this(x.toDouble(), y.toDouble(), z.toDouble(), w.toDouble())
    constructor(base: Vec4) : this(base.x, base.y, base.z, base.w)
    constructor(base: Vector4<*,*>) : this(base.x, base.y, base.z, base.w)

    override val self
        get() = this

    override fun createVec2(a: Double, b: Double): MutableVec2 = MutableVec2(a,b)

    override fun createVec3(a: Double, b: Double, c: Double): MutableVec3 = MutableVec3(a,b,c)

    override fun create(x: Double, y: Double, z: Double, w: Double): MutableVec4 = MutableVec4(x, y, z, w)

    companion object {
        val one get() = MutableVec4(1.0, 1.0, 1.0, 1.0)
        val zero get() = MutableVec4(0.0, 0.0, 0.0, 0.0)
        val right get() = MutableVec4(1.0, 0.0, 0.0, 0.0)
        val left get() = MutableVec4(-1.0, 0.0, 0.0, 0.0)
        val up get() = MutableVec4(0.0, 1.0, 0.0, 0.0)
        val down get() = MutableVec4(0.0, -1.0, 0.0, 0.0)
        val forward get() = MutableVec4(0.0, 0.0, 1.0, 0.0)
        val backward get() = MutableVec4(0.0, 0.0, -1.0, 0.0)
        val negativeInfinity get() = MutableVec4(Double.NEGATIVE_INFINITY)
        val positiveInfinity get() = MutableVec4(Double.POSITIVE_INFINITY)
    }

    /**Reflects the vector from [normal].*/
   /*override infix fun reflectFrom(normal: Vec4): MutableVec4 {
        val norm = normal.normalized
        val factor = -2.0 * this dot norm
        return MutableVec4(factor * norm + this)
    }
    *//**Reflects the vector from [normal].*//*
    override infix fun reflectFrom(normal: Vec3) = reflectFrom(normal.vec4)
    *//**Reflects the vector from [normal].*//*
    override infix fun reflectFrom(normal: Vec2) = reflectFrom(normal.vec4)*/

    override fun equals(other: Any?) = other is MutableVec4 && x == other.x && y == other.y && z == other.z && w == other.w
    override fun hashCode() = 31 * (31 * (31 * x.hashCode() + y.hashCode()) + z.hashCode()) + w.hashCode()
}